<?php

final class ectools_payment_plugin_alipay extends ectools_payment_app implements ectools_interface_payment_app {

    public $name = '支付宝支付';

    public $app_name = '支付宝支付接口';

    public $app_key = 'alipay';

    public $app_rpc_key = 'alipay';

    public $display_name = '支付宝';

    public $curname = 'CNY';

    public $ver = '1.0';

    public $platform = 'ispc';

    public $supportCurrency = array(
        "CNY" => "01"
    );

    public function __construct($app) {
        parent::__construct($app);
        
        // $this->callback_url = $this->app->base_url(true)."/apps/".basename(dirname(__FILE__))."/".basename(__FILE__);
        $this->notify_url = kernel::openapi_url('openapi.ectools_payment/parse/' . $this->app->app_id . '/ectools_payment_plugin_alipay_server', 'callback');
        if (preg_match("/^(http):\/\/?([^\/]+)/i", $this->notify_url, $matches)) {
            $this->notify_url = str_replace('http://', '', $this->notify_url);
            $this->notify_url = preg_replace("|/+|", "/", $this->notify_url);
            $this->notify_url = "http://" . $this->notify_url;
        } else {
            $this->notify_url = str_replace('https://', '', $this->notify_url);
            $this->notify_url = preg_replace("|/+|", "/", $this->notify_url);
            $this->notify_url = "https://" . $this->notify_url;
        }
        $this->callback_url = kernel::openapi_url('openapi.ectools_payment/parse/' . $this->app->app_id . '/ectools_payment_plugin_alipay', 'callback');
        if (preg_match("/^(http):\/\/?([^\/]+)/i", $this->callback_url, $matches)) {
            $this->callback_url = str_replace('http://', '', $this->callback_url);
            $this->callback_url = preg_replace("|/+|", "/", $this->callback_url);
            $this->callback_url = "http://" . $this->callback_url;
        } else {
            $this->callback_url = str_replace('https://', '', $this->callback_url);
            $this->callback_url = preg_replace("|/+|", "/", $this->callback_url);
            $this->callback_url = "https://" . $this->callback_url;
        }
        // $this->submit_url = 'https://www.alipay.com/cooperate/gateway.do?_input_charset=utf-8';
        // ajx 按照相应要求请求接口网关改为一下地址
        $this->submit_url = 'https://mapi.alipay.com/gateway.do?_input_charset=utf-8';
        $this->submit_method = 'POST';
        $this->submit_charset = 'utf-8';
    }

    public function admin_intro() {
        $regIp = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : $_SERVER['HTTP_HOST'];
        return '<img src="' . $this->app->res_url . '/payments/images/ALIPAY.gif">';
    }

    public function setting() {
        return array(
            'pay_name' => array(
                'title' => app::get('ectools')->_('支付方式名称'),
                'type' => 'string',
                'validate_type' => 'required'
            ),
            'mer_id' => array(
                'title' => app::get('ectools')->_('合作者身份(parterID)'),
                'type' => 'string',
                'validate_type' => 'required'
            ),
            'mer_key' => array(
                'title' => app::get('ectools')->_('交易安全校验码(key)'),
                'type' => 'string',
                'validate_type' => 'required'
            ),
            'order_by' => array(
                'title' => app::get('ectools')->_('排序'),
                'type' => 'string',
                'label' => app::get('ectools')->_('整数值越小,显示越靠前,默认值为1')
            ),
            'support_cur' => array(
                'title' => app::get('ectools')->_('支持币种'),
                'type' => 'text hidden cur',
                'options' => $this->arrayCurrencyOptions
            ),
            'real_method' => array(
                'title' => app::get('ectools')->_('选择接口类型'),
                'type' => 'select',
                'options' => array(
                    '0' => app::get('ectools')->_('使用标准双接口'),
                    '2' => app::get('ectools')->_('使用担保交易接口'),
                    '1' => app::get('ectools')->_('使用即时到帐交易接口')
                ),
                'tip' => '消费者如用担保交易充值，需在支付宝后台进行确认操作，充值款才可到账'
            ),
            'pay_fee' => array(
                'title' => app::get('ectools')->_('交易费率'),
                'type' => 'pecentage',
                'validate_type' => 'number'
            ),
            'pay_brief' => array(
                'title' => app::get('ectools')->_('支付方式简介'),
                'type' => 'textarea'
            ),
            'pay_desc' => array(
                'title' => app::get('ectools')->_('描述'),
                'type' => 'html',
                'includeBase' => true
            ),
            'pay_type' => array(
                'title' => app::get('ectools')->_('支付类型(是否在线支付)'),
                'type' => 'hidden',
                'name' => 'pay_type'
            ),
            'status' => array(
                'title' => app::get('ectools')->_('是否开启此支付方式'),
                'type' => 'radio',
                'options' => array(
                    'false' => app::get('ectools')->_('否'),
                    'true' => app::get('ectools')->_('是')
                ),
                'name' => 'status'
            )
        );
    }

    public function intro() {
        return app::get('ectools')->_('支付宝（中国）网络技术有限公司是国内领先的独立第三方支付平台，由阿里巴巴集团创办。支付宝致力于为中国电子商务提供“简单、安全、快速”的在线支付解决方案。') . '
<a target="_blank" href="https://www.alipay.com/static/utoj/utojindex.htm">' . app::get('ectools')->_('如何使用支付宝支付？') . '</a>';
    }

    public function dopay($payment) {
        $mer_id = trim($this->getConf('mer_id', __CLASS__));
        $mer_id = $mer_id;
        $mer_key = trim($this->getConf('mer_key', __CLASS__));
        $mer_key = $mer_key;
        
        $subject = $payment['body'];
        if (isset($payment['receiveArr'])) {
            foreach ($payment['receiveArr'] as $key => $value) {
                $curvalue = str_replace("'", '`', $value);
                $curvalue = str_replace('"', '`', $curvalue);
                $payment['receiveArr'][$key] = $curvalue;
            }
        }
        $subject = str_replace("'", '`', trim($subject));
        $subject = str_replace('"', '`', $subject);
        $orderDetail = str_replace("'", '`', trim($orderDetail));
        $orderDetail = str_replace('"', '`', $orderDetail);
        
        $virtual_method = $this->getConf('virtual_method', __CLASS__); // $config['virtual_method'];
        $real_method = $this->getConf('real_method', __CLASS__); // $config['real_method'];
        
        switch ($real_method) {
            case '0':
                $this->add_field('service', 'trade_create_by_buyer'); // form['service'] = 'trade_create_by_buyer';
                $this->add_field('price', number_format($payment['cur_money'], 2, ".", ""));
                break;
            case '1':
                $this->add_field('service', 'create_direct_pay_by_user'); // $form['service'] = 'create_direct_pay_by_user';
                $this->add_field('total_fee', number_format($payment['cur_money'], 2, ".", ""));
                break;
            case '2':
                $this->add_field('service', 'create_partner_trade_by_buyer'); // $form['service'] = 'create_partner_trade_by_buyer';
                $this->add_field('price', number_format($payment['cur_money'], 2, ".", ""));
                break;
        }
        
        $this->add_field('logistics_type', 'POST');
        $this->add_field('logistics_payment', 'BUYER_PAY');
        $this->add_field('logistics_fee', '0.00');
        
        $this->add_field('agent', 'C433530444855584111X');
        $this->add_field('payment_type', 1);
        $this->add_field('partner', $mer_id);
        $this->add_field('return_url', $this->callback_url);
        $this->add_field('notify_url', $this->notify_url);
        if (isset($payment['subject']) && $payment['subject'])
            $this->add_field('subject', $payment['subject']);
        elseif ($subject)
            $this->add_field('subject', $subject);
        else
            $this->add_field('subject', '预存款');
        if (isset($payment['body']) && $payment['body'])
            $this->add_field('body', $payment['body']);
        else
            $this->add_field('body', app::get('ectools')->_('网店订单'));
        $this->add_field('out_trade_no', $payment['payment_id']);
        $this->add_field('quantity', 1);
        
        if (preg_match("/^\d{16}$/", $mer_id)) {
            $this->add_field('seller_id', $mer_id);
        } else {
            $this->add_field('seller_email', $mer_id);
        }
        
        $this->add_field('buyer_msg', $payment['remark'] ? $payment['remark'] : app::get('ectools')->_('无留言'));
        
        if (isset($payment['receiveArr']['name']) && $payment['receiveArr']['name']) {
            $this->add_field('receive_name', $payment['receiveArr']['name']);
        }
        if (isset($payment['receiveArr']['addr']) && $payment['receiveArr']['addr']) {
            $this->add_field('receive_address', $payment['receiveArr']['addr']);
        }
        if (isset($payment['receiveArr']['zip']) && $payment['receiveArr']['zip']) {
            $this->add_field('receive_zip', $payment['receiveArr']['zip']);
        }
        if (isset($payment['receiveArr']['telephone']) && $payment['receiveArr']['telephone']) {
            $this->add_field('receive_phone', $payment['receiveArr']['telephone']);
        }
        if (isset($payment['receiveArr']['mobile']) && $payment['receiveArr']['mobile']) {
            $this->add_field('receive_mobile', $payment['receiveArr']['mobile']);
        }
        
        $this->add_field('_input_charset', 'utf-8');
        $this->add_field('sign', $this->_get_mac($mer_key));
        $this->add_field('sign_type', 'MD5');
        
        unset($this->fields['_input_charset']);
        
        if ($this->is_fields_valiad()) {
            // Generate html and send payment.
            echo $this->get_html();
            exit();
        } else {
            return false;
        }
    }

    public function is_fields_valiad() {
        return true;
    }

    public function callback(&$recv) {
        // 键名与pay_setting中设置的一致
        $mer_id = $this->getConf('mer_id', __CLASS__);
        $mer_id = $mer_id == '' ? '2088002003028751' : $mer_id;
        $mer_key = $this->getConf('mer_key', __CLASS__);
        $mer_key = $mer_key == '' ? 'afsvq2mqwc7j0i69uzvukqexrzd0jq6h' : $mer_key;
        
        if ($this->is_return_vaild($recv, $mer_key)) {
            $ret['payment_id'] = $recv['out_trade_no'];
            $ret['account'] = $mer_id;
            $ret['bank'] = app::get('ectools')->_('支付宝');
            $ret['pay_account'] = app::get('ectools')->_('付款帐号');
            $ret['currency'] = 'CNY';
            $ret['money'] = $recv['total_fee'];
            $ret['paycost'] = '0.000';
            $ret['cur_money'] = $recv['total_fee'];
            $ret['trade_no'] = $recv['trade_no'];
            $ret['t_payed'] = strtotime($recv['notify_time']) ? strtotime($recv['notify_time']) : time();
            $ret['pay_app_id'] = "alipay";
            $ret['pay_type'] = 'online';
            $ret['memo'] = $recv['body'];
            
            switch ($recv['trade_status']) {
                case 'TRADE_FINISHED':
                    if ($recv['is_success'] == 'T') {
                        $ret['status'] = 'succ';
                    } else {
                        $ret['status'] = 'failed';
                    }
                    break;
                case 'TRADE_SUCCESS':
                    if ($recv['is_success'] == 'T') {
                        $ret['status'] = 'succ';
                    } else {
                        $ret['status'] = 'failed';
                    }
                    break;
                case 'WAIT_SELLER_SEND_GOODS':
                    if ($recv['is_success'] == 'T') {
                        $ret['status'] = 'progress';
                    } else {
                        $ret['status'] = 'failed';
                    }
                    break;
                case 'TRADE_SUCCES': // 高级用户
                    if ($recv['is_success'] == 'T') {
                        $ret['status'] = 'succ';
                    } else {
                        $ret['status'] = 'failed';
                    }
                    break;
            }
        } else {
            $message = 'Invalid Sign';
            $ret['status'] = 'invalid';
        }
        
        return $ret;
    }

    public function gen_form() {
        $tmp_form = '<a href="javascript:void(0)" onclick="document.applyForm.submit();">' . app::get('ectools')->_('立即申请支付宝') . '</a>';
        $tmp_form .= "<form name='applyForm' method='" . $this->submit_method . "' action='" . $this->submit_url . "' target='_blank'>";
        // 生成提交的hidden属性
        foreach ($this->fields as $key => $val) {
            $tmp_form .= "<input type='hidden' name='" . $key . "' value='" . $val . "'>";
        }
        
        $tmp_form .= "</form>";
        
        return $tmp_form;
    }

    public function _get_mac($key) {
        ksort($this->fields);
        reset($this->fields);
        $mac = "";
        foreach ($this->fields as $k => $v) {
            $mac .= "&{$k}={$v}";
        }
        $mac = substr($mac, 1);
        $mac = md5($mac . $key); // 验证信息
        return $mac;
    }

    public function is_return_vaild($form, $key) {
        ksort($form);
        foreach ($form as $k => $v) {
            if ($k != 'sign' && $k != 'sign_type') {
                $signstr .= "&$k=$v";
            }
        }
        
        $signstr = ltrim($signstr, "&");
        $signstr = $signstr . $key;
        
        if ($form['sign'] == md5($signstr)) {
            return true;
        }
        // 记录返回失败的情况
        logger::error(app::get('ectools')->_('支付单号：') . $form['out_trade_no'] . app::get('ectools')->_('签名验证不通过，请确认！') . "\n");
        logger::error(app::get('ectools')->_('本地产生的加密串：') . $signstr);
        logger::error(app::get('ectools')->_('支付宝传递打过来的签名串：') . $form['sign']);
        $str_xml .= "<alipayform>";
        foreach ($form as $key => $value) {
            $str_xml .= "<$key>" . $value . "</$key>";
        }
        $str_xml .= "</alipayform>";
        
        return false;
    }
}
